// Location.cs
// 
// Copyright (C) 2008 Jean-André Santoni
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//

using System;
using System.Text.RegularExpressions;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using Astrognome;

namespace Astrognome
{
	[Serializable()]
	
	public class Location : ISerializable
	{
		private string country;
		private string city;
		private Latitude latitude;
		private Longitude longitude;
		
		public string    Country   { get { return country;   } set { country = value;   } }
		public string    City      { get { return city;      } set { city = value;      } }
		public Latitude  Latitude  { get { return latitude;  } set { latitude = value;  } }
		public Longitude Longitude { get { return longitude; } set { longitude = value; } }
		
		public Location ()
		{
			Country = "Nowhere";
			City = "Nowhere";
			Latitude = new Latitude();
			Longitude = new Longitude();
		}
		
		public Location (string country, string city, string latitude, string longitude)
		{
			Country = country;
			City = city;
			Latitude = new Latitude(latitude);
			Longitude = new Longitude(longitude);
		}
		
		public Location (SerializationInfo info, StreamingContext ctx)
		{
			Country =   (string)    info.GetValue("Country",   typeof(string));
			City =      (string)    info.GetValue("City",      typeof(string));
			Latitude =  (Latitude)  info.GetValue("Latitude",  typeof(Latitude));
			Longitude = (Longitude) info.GetValue("Longitude", typeof(Longitude));
		}

		public void GetObjectData (SerializationInfo info, StreamingContext ctx)
		{
			info.AddValue("Country",   Country);
			info.AddValue("City",      City);
			info.AddValue("Latitude",  Latitude);
			info.AddValue("Longitude", Longitude);
		}
		
		public override string ToString ()
		{
			return City + " (" + Country + ")";
		}
	}
	
	public abstract class Coordinate
	{
		private int degree;
		private char direction;
		private int minute;
		
		public int  Degree    { get { return degree;    } set { degree = value;    } }
		public char Direction { get { return direction; } set { direction = value; } }
		public int  Minute    { get { return minute;    } set { minute = value;    } }
		
		public override string ToString ()
		{
			return Degree.ToString() + Direction.ToString() + Minute.ToString();
		}
	}
	
	[Serializable()]
	
	public class Latitude : Coordinate, ISerializable
	{		
		public Latitude ()
		{
			Degree = 0;
			Direction = 'N';
			Minute = 0;
		}
		
		public Latitude (int degree, char direction, int minute)
		{
			Degree = degree;
			Direction = direction;
			Minute = minute;
		}
		
		public Latitude (string str)
		{
			Regex reg = new Regex("^([0-9]+)([NS])([0-9]+)$");
			if (reg.IsMatch(str))
			{
				Degree = Convert.ToInt32(reg.Match(str).Groups[1].Value);
				Direction = Convert.ToChar(reg.Match(str).Groups[2].Value);
				Minute = Convert.ToInt32(reg.Match(str).Groups[3].Value);
			}
		}
		
		public Latitude (SerializationInfo info, StreamingContext ctx)
		{
			Degree =    (int)  info.GetValue("Degree",    typeof(int));
			Direction = (char) info.GetValue("Direction", typeof(char));
			Minute =    (int)  info.GetValue("Minute",    typeof(int));
		}

		public void GetObjectData (SerializationInfo info, StreamingContext ctx)
		{
			info.AddValue("Degree",    Degree);
			info.AddValue("Direction", Direction);
			info.AddValue("Minute",    Minute);
		}
	}
	
	[Serializable()]
	
	public class Longitude : Coordinate, ISerializable
	{
		public Longitude ()
		{
			Degree = 0;
			Direction = 'E';
			Minute = 0;
		}
		
		public Longitude (int degree, char direction, int minute)
		{
			Degree = degree;
			Direction = direction;
			Minute = minute;
		}
		
		public Longitude (string str)
		{
			Regex reg = new Regex("^([0-9]+)([EW])([0-9]+)$");
			if (reg.IsMatch(str))
			{
				Degree = Convert.ToInt32(reg.Match(str).Groups[1].Value);
				Direction = Convert.ToChar(reg.Match(str).Groups[2].Value);
				Minute = Convert.ToInt32(reg.Match(str).Groups[3].Value);
			}
		}
		
		public Longitude (SerializationInfo info, StreamingContext ctx)
		{
			Degree =    (int)  info.GetValue("Degree",    typeof(int));
			Direction = (char) info.GetValue("Direction", typeof(char));
			Minute =    (int)  info.GetValue("Minute",    typeof(int));
		}

		public void GetObjectData (SerializationInfo info, StreamingContext ctx)
		{
			info.AddValue("Degree",    Degree);
			info.AddValue("Direction", Direction);
			info.AddValue("Minute",    Minute);
		}
	}	
}
